﻿using KludgeBox;
using KludgeBox.Events;
using KludgeBox.Net;
using KludgeBox.Net.Packets;
using VectorSurvivors.GameWorld;

namespace VectorSurvivors.Multiplayer;



[GameService]
public class MultiplayerService
{
    private PacketBuffer _queueToServer = new();
    private PacketBuffer _queueToClients = new();
    
    public World CurrentWorld { get; private set; }

    [EventListener]
    public void OnRegisterWorldRequest(RegisterWorldRequest worldRegister)
    {
        CurrentWorld = worldRegister.World;
    }
    
    [EventListener]
    public void OnWorldNetworkProcessEvent(WorldNetworkProcessEvent networkProcess)
    {
        if(Network.IsClient)
            Network.SendPacketsToServer(_queueToServer);
        
        if(Network.IsServer)
            Network.SendPacketsToClients(_queueToClients);
    }


    [EventListener]
    public void OnSendPacketToServerRequest(SendPacketToServerRequest request)
    {
        if (!Network.IsClient) return;
        SendPacket(toServer: true, 
            packet: request.Packet, 
            forceReliable: request.ForceReliable, 
            forceNow: request.ForceNow);
    }

    [EventListener]
    public void OnSendPacketToClientsRequest(SendPacketToClientsRequest request)
    {
        if (!Network.IsServer) return;
        SendPacket(toServer: false,
            packet: request.Packet, 
            forceReliable: request.ForceReliable, 
            forceNow: request.ForceNow);
    }

    [EventListener]
    public void OnStartServerRequest(StartServerRequest request)
    {
        if(Network.Mode is not NetworkMode.None) return;

        Network.CreateServer(request.Port);
    }

    [EventListener]
    public void OnConnectToServerRequest(ConnectToServerRequest connectRequest)
    {
        if (Network.Mode is not NetworkMode.None) return;

        Network.ConnectToRemoteServer(connectRequest.Host, connectRequest.Port);
    }

    private void SendPacket(bool toServer, AbstractPacket packet, bool forceReliable, bool forceNow)
    {
        if (packet.IsBufferable && !forceNow)
        {
            var queue = toServer ? _queueToServer : _queueToClients;
            queue.EnqueuePacket(packet);
        }
        else
        {
            if (!toServer)
            {
                Network.SendPacketToClients(packet, packet.IsReliable || forceReliable);
            }
            else
            {
                Network.SendPacketToServer(packet, packet.IsReliable || forceReliable);
            }
            
        }
    }
}